#include "GamePlayLayer.h"
#include <SEngine/Project/Project.h>
#include <SECore/CoreApplication.h>
#include <SEGamePlay/Render/Resourses/GamePlayResourse.h>
#include <SEngine/Render/BaseRenderer.h>
#include <SEngine/Render/RenderFeature/FrameRenderFeature.h>
#include <SEngine/Render/RenderFeature/UBORenderFeature.h>
#include <SEngine/Render/Descriptors/SceneDescriptor.h>
#include <SERender/Descriptors/FrameDescriptor.h>
#include <SEngine/Ecs/Components/CameraComp.h>
#include <SEGamePlay/Render/RenderPass/ModelRenderPass.h>
#include <SEGamePlay/Render/RenderPass/ShadowRenderPass.h>
#include <SEngine/Render/RenderPass/SkyboxRenderPass.h>
#include <SEngine/Ecs/Components/ScriptComp.h>
#include <filesystem>
#include <SEDebug/Log/Log.h>

namespace SEngine
{
    void GamePlayLayer::Attach()
    {
        ResShaderInit();
        ResModelInit();
        ResFontInit();
        ResTextureInit();

        ProjectOption opt;
        if (m_argc == 2) {
            opt.path = m_argv[1];
            std::filesystem::path path(opt.path);
            opt.name = path.filename().string();
            Log::GetInstance().Info("Load Project {}", opt.path);
        } else {
            opt.path = "C:\\Users\\18357\\Desktop\\Test\\Test.seproject";
            opt.name = "Test.seproject";
            Log::GetInstance().Warn("UnLoad Project {}", opt.path);
        }
        Project project(std::move(opt));
        project.Deserialization();
        m_app.AddDescriptor<Project>(std::move(project));

        m_renderer = std::make_unique<BaseRenderer>(std::make_unique<CurrentDrive>());
        m_renderer->Descriptor<RenderPass>::AddDescriptor(std::make_unique<SkyboxRenderPass>(*m_renderer));
        m_renderer->Descriptor<RenderPass>::AddDescriptor(std::make_unique<ModelRenderPass>(*m_renderer));
        m_renderer->Descriptor<RenderPass>::AddDescriptor(std::make_unique<ShadowRenderPass>(*m_renderer));
        m_renderer->AnyDescriptor::AddDescriptor<SceneDescriptor>(std::move(SceneDescriptor{project.GetScene()}));

        project.GetScene()->Components<ScriptComp>([](Actor & actor, ScriptComp & comp) { comp.m_enabled = true; });
    }

    void GamePlayLayer::Update(int delta)
    {
        int w, h;
        std::tie(w, h) = m_app .GetWindow()->GetWindowSize();
        Camera * camera = nullptr;
        m_renderer->AnyDescriptor::GetDescriptor<SceneDescriptor>()->get().scene->Components<CameraComp>([&](Actor & actor, CameraComp & comp) {
            camera = &comp.m_camera;
        });
        if (!camera) {
            return;
        }
        m_renderer->AnyDescriptor::AddDescriptor<FrameDescriptor>(FrameDescriptor{0, 0, w, h, *camera});
        m_renderer->BeginFrame();
        m_renderer->DrawFrame();
        m_renderer->EndFrame();
    }

} // namespace SEngine

